//===============================================================================
// Microsoft patterns & practices
// Guidance Explorer Offline Client
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================



using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;

namespace GuidanceExplorer.Model
{
    public class Folder : ILibraryNodes
    {
        /// <summary>
        /// Factory.
        /// </summary>
        /// <returns></returns>
        public static Folder New()
        {
            return new Folder();
        }

        #region Private members

        /// <summary>
        /// The columns for this folder.
        /// </summary>
        private ColumnCollection _columns = ColumnCollection.New();

        /// <summary>
        /// The list of views defined in this structure.
        /// </summary>
        private ViewCollection _views = ViewCollection.New();

        /// <summary>
        /// The list of folders defined in this structure.
        /// </summary>
        private FolderCollection _folders = FolderCollection.New();

        /// <summary>
        /// The parent folder reference.
        /// </summary>
        private Folder _parentFolder;

        /// <summary>
        /// The caption of the view.
        /// </summary>
        private string _caption;

        /// <summary>
        /// The outer container of the view.
        /// </summary>
        private FolderStructure _container;
        protected string _id = Guid.NewGuid().ToString();



        #endregion

        /// <summary>
        /// Private default constructor.
        /// </summary>
        protected Folder() 
        {
            Checklists = ChecklistCollection.New();
        }

        #region Public properties

        /// <summary>
        /// The caption of the view.
        /// </summary>
        [Browsable(true)]
        [ReadOnly(true)]
        public string Caption
        {
            get { return _caption; }
            set 
            { 
                _caption = value;
                UpdateDateTime();
            }
        }
        /// <summary>
        /// The number of views contained in the folder.
        /// This property was added to display info in the properties pane.
        /// </summary>
        [Browsable(true)]
        [ReadOnly(true)]
        public int ViewCount
        {
            get { return AllViews.Count; }
        }

        /// <summary>
        /// The list of views defined in this structure.
        /// </summary>
        [Browsable(false)]
        public ViewCollection Views
        {
            get { return _views; }
            set { _views = value; }
        }

        /// <summary>
        /// The list of checklists defined in this structure.
        /// </summary>
        [Browsable(false)]
        public ChecklistCollection Checklists { get; set; }

        /// <summary>
        /// The list of all child views.
        /// </summary>
        [Browsable(false)]
        public ViewCollection AllViews
        {
            get
            {
                ViewCollection views = ViewCollection.New();
                foreach (View view in _views.Values)
                {
                    views.Add(view.Caption, view);
                }
                foreach (Folder folder in _folders.Values)
                {
                    foreach (View view in folder.AllViews.Values)
                    {
                        views.Add(view.Id, view);
                    }
                }
                return views;
            }
        }

        /// <summary>
        /// The list of folders defined in this structure.
        /// </summary>
        [Browsable(false)]
        public FolderCollection Folders
        {
            get { return _folders; }
            set { _folders = value; }
        }

        /// <summary>
        /// The parent folder reference.
        /// </summary>
        [Browsable(false)]
        public Folder ParentFolder
        {
            get { return _parentFolder; }
            set { _parentFolder = value; }
        }

        /// <summary>
        /// The outer container of the view.
        /// </summary>
        [Browsable(false)]
        public FolderStructure Container
        {
            get { return _container; }
            set { _container = value; }
        }

        /// <summary>
        /// The columns for this folder.
        /// </summary>
        [Browsable(false)]
        public ColumnCollection Columns
        {
            get { return _columns; }
            set { _columns = value; }
        }

        /// <summary>
        /// Folders does not have Items, they only can be iterated for contained items.
        /// </summary>
        [Browsable(false)]
        public bool HasItems
        {
            get { return false; }
        }

        /// <summary>
        /// The items collection can't be set.
        /// </summary>
        [Browsable(false)]
        public bool CanSetItems
        {
            get { return false; }
        }

        /// <summary>
        /// The list of items in the folder.
        /// </summary>
        [Browsable(false)]
        public GuidanceItemCollection Items
        {
            get { throw new Exception("Folders does not have Items."); }
            set { throw new Exception("Folders does not have Items."); }
        }
        public String Id
        {
            get
            {
                return _id;
            }
        }

        #endregion

        #region IEnumerable<GuidanceItem> Members

        public IEnumerator<GuidanceItem> GetEnumerator()
        {
            foreach (Folder folder in _folders.Values)
            {
                foreach (GuidanceItem item in folder)
                {
                    yield return item;
                }
            }

            foreach (View view in _views.Values)
            {
                foreach (GuidanceItem item in view)
                {
                    yield return item;
                }
            }
            foreach (Checklist checklist in Checklists.Values)
            {
                foreach (GuidanceItem item in checklist)
                {
                    yield return item;
                }
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion

        public override bool Equals(object obj)
        {
            Folder other = obj as Folder;
            if (other != null)
            {
                bool caption = (_caption == other._caption);
                bool columns = (_columns.Equals(other._columns));
                bool folders = (_folders.Equals(other._folders));
                bool parentFolder = (_parentFolder == other._parentFolder);
                bool views = (_views.Equals(other._views));
                return (caption && columns && folders && parentFolder && views);
            }
            else
            {
                return base.Equals(obj);
            }
        }

        public override int GetHashCode()
        {
            return _caption.GetHashCode();
        }

        /// <summary>
        /// Get the container library or null if this is a MyViews folder.
        /// </summary>
        /// <returns></returns>
        public Library GetContainerLibrary()
        {
            if (ParentFolder != null)
            {
                Folder tempFolder;
                for (tempFolder = ParentFolder; tempFolder.ParentFolder != null; tempFolder = tempFolder.ParentFolder)
                { }
                return tempFolder.Container as Library;
            }
            else
            {
                return Container as Library;
            }
        }

        /// <summary>
        /// Remove the folder from its container.
        /// </summary>
        public void Remove()
        {
            if (ParentFolder == null)
            {
				Container.Folders.Remove(this.Caption);

            }
            else
            {
				ParentFolder.Folders.Remove(this.Caption);
            }
        }

        public void UpdateDateTime()
        {
            foreach (Folder folder in _folders.Values)
            {
                folder.UpdateDateTime();
            }

            foreach (View view in _views.Values)
            {
                view.LastUpdate = DateTime.UtcNow;
            }
        }

        public Folder Clone()
        {
            Folder newFolder = new Folder();

            newFolder._caption = Caption;
            newFolder._columns = Columns;
            newFolder._container = Container;
            newFolder._parentFolder = ParentFolder;

            foreach (Folder folder in _folders.Values)
            {
                Folder newChildFolder = folder.Clone();
                newFolder._folders.Add(newChildFolder.Caption, newChildFolder);
            }

            foreach (View view in _views.Values)
            {
                if (view is SearchView)
                {
                    newFolder._views.Add(view.Id, view);
                }
                else
                {
                    View newView = view.Clone();
                    newFolder._views.Add(newView.Id, newView);
                }
            }

            return newFolder;
        }
        
    }
}

